Rustでシリアル通信する
Introduction
諸事情によりRustでシリアル通信をしようと思い、
serialportクレートを使ってみた記録です。
Environment
今回試した環境は以下のとおりです。
- MacBook Pro (13-inch, M1, 2020)
- OS : MacOS 12.4
- Rust : 1.70.0
Setup
私のつかっているPCにはシリアルポートがないので、
仮想的なシリアルポートを用意する必要があります。
socatを使えば用意できるので、Homebrewでインストールします。
% brew install socat
socatコマンドで仮想シリアルポートを作成します。
% socat -d -d pty,raw,echo=0 pty,raw,echo=0 2023/06/09 12:39:00 socat[18488] N PTY is /dev/ttys006 2023/06/09 12:39:00 socat[18488] N PTY is /dev/ttys007 2023/06/09 12:39:00 socat[18488] N starting data transfer loop with FDs [5,5] and [7,7]
「-d -d」でデバッグ出力用オプションを指定して2つの仮想シリアルポートを作成します。
ここでは/dev/ttys006と/dev/ttys007の2つのポートが作成されました。
Create Rust Program
ではCargoでRustプロジェクトを作成します。
% cargo new rust-serial
Cargo.tomlにserialportクレートを追記します。
(cargo add serialportでもOK)
[dependencies] serialport = "4.2.1"
main.rsに、さきほど作成した仮想シリアルポートにするコードを記述します。
作成したポートのうち、1つを読み取り側、もう1つを書き込み側として使います。
use std::error::Error; use std::io::prelude::*; use std::time::Duration; fn main() -> Result<(), Box<dyn Error>> { let port_name_read = "/dev/ttys006";//socatで作成したポート let port_name_read2 = "/dev/ttys007";//socatで作成したポート let mut port1 = serialport::new(port_name_read, 0) .timeout(Duration::from_millis(100)) .open()?; let mut port2 = serialport::new(port_name_read2, 0) .timeout(Duration::from_millis(10)) .open().expect("Failed to open port"); let mut buf: Vec<u8> = vec![0; 1000]; let output = "hello".as_bytes(); loop { println!("Write Buffer."); match port1.write(output) { Ok(_) => std::io::stdout().flush()?, Err(e) => eprintln!("{:?}", e), } println!("Read Buffer."); match port2.read(buf.as_mut_slice()) { Ok(t) => { let bytes = &buf[..t]; let string = String::from_utf8(bytes.to_vec())?; //println!("bytes: {:?}", bytes); println!("string: {:?}", string); } Err(e) => eprintln!("{:?}", e), } std::thread::sleep(Duration::from_millis(1000)); } }
実行してみます。
シリアルポートへの送受信ができていることがわかります。
% cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.08s Running `target/debug/serial` Write Buffer. Read Buffer. string: "hello" Write Buffer. Read Buffer. string: "hello" ・ ・
Summary
Rustでシリアルポート通信ができました。
しかし今回、通信時にbaud_rate(シリアル通信時に送受信速度を表すパラメータ)を
指定するとエラーになってしまいました。(なので0を指定している)
※serialport::newの第2引数
これが環境の問題なのかsocatで作成したからなのか不明なので
実際にシリアルポートがあるPCで試してみたいところです。